package com.googlecode.biglog.appender.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.Date;

import javax.sql.DataSource;

import net.sf.common.util.BeanUtils;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.jdbc.JDBCAppender;
import org.springframework.jdbc.datasource.DataSourceUtils;

public class JdbcAppender extends JDBCAppender {
	private String applicationContextName;
	private String dataSourceBeanName;
	private DataSource dataSource;
	private BeanUtils beanUtils;
	private boolean stopDataSource;
	public String getApplicationContextName() {
		return applicationContextName;
	}
	public void setApplicationContextName(String applicationContextName) {
		this.applicationContextName = applicationContextName;
	}
	public String getDataSourceBeanName() {
		return dataSourceBeanName;
	}
	public void setDataSourceBeanName(String dataSourceBeanName) {
		this.dataSourceBeanName = dataSourceBeanName;
	}

	@Override
	protected Connection getConnection() throws SQLException {
		if (stopDataSource)
			return super.getConnection();

		if (applicationContextName == null || dataSourceBeanName == null) {
			stopDataSource = true;
			return super.getConnection();
		}

		if (beanUtils == null) {
			stopDataSource = true;
			try {
				beanUtils = BeanUtils.getInstance(applicationContextName);
			} finally {
				stopDataSource = false;
			}
		}

		if (beanUtils == null)
			return super.getConnection();

		try {
			stopDataSource = true;
			dataSource = beanUtils.get(dataSourceBeanName, DataSource.class);
			return DataSourceUtils.getConnection(dataSource);
		} catch (Exception e) {
			return super.getConnection();
		} finally {
			stopDataSource = false;
		}
	}
	@Override
	protected void closeConnection(Connection con) {
		if (con == null)
			return;
		if (dataSource == null)
			super.closeConnection(con);
		else
			DataSourceUtils.releaseConnection(con, dataSource);
	}

	@Override
	protected void execute(String sql) throws SQLException {
		if (sql == null)
			return;
		Connection con = null;
		Statement stmt = null;
		try {
			con = getConnection();
			if (sql.indexOf(":time") == -1) {
				stmt = con.createStatement();
				stmt.executeUpdate(sql);
			} else {
				Timestamp time = new Timestamp(new Date().getTime());
				sql = StringUtils.replace(sql, ":time", "?");

				con = getConnection();
				PreparedStatement pstmt = con.prepareStatement(sql);
				stmt = pstmt;
				pstmt.setTimestamp(1, time);
				pstmt.executeUpdate();
			}
		} catch (SQLException e) {
			throw e;
		} finally {
			if (stmt != null)
				stmt.close();
			closeConnection(con);
		}
	}
}
